home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / AMScen_0_9.lha / AMScen / mall.m < prev    next >
Text File  |  1995-01-21  |  39KB  |  1,166 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1995 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * mall.m - define the minimall in the starter dungeon.
  9.  */
  10.  
  11. private tp_mall CreateTable().
  12. use tp_mall
  13.  
  14. /*
  15.  * NOTE: two rooms, r_arrivals and r_lostAndFound, are actually created
  16.  *    in 'util.m'. Since the structure and connections of those rooms are
  17.  *    set up in this file, this file must be sourced by the same player
  18.  *    who sources 'util.m' (normally SysAdmin), or those two rooms must
  19.  *    be public, at least long enough to allow the building here.
  20.  *    We are also dependent on some properties relevant to specific verbs,
  21.  *    p_rRegisterAction and p_rBuyAction, so we need to have 'verbs.m'
  22.  *    sourced first.
  23.  */
  24.  
  25. /* Most are private since we don't want anybody changing the stuff in the
  26.    minimall area. */
  27.  
  28. /* All rooms in this area use this routine as their graphics drawing routine.
  29.    It works with the code in 'graphics.m'. */
  30.  
  31. define tp_mall MINI_MALL_ID NextEffectId().
  32.  
  33. define tp_mall proc drawMiniMall()void:
  34.  
  35.     if not KnowsEffect(nil, MINI_MALL_ID) then
  36.     DefineEffect(nil, MINI_MALL_ID);
  37.  
  38.     GSetImage(nil, "mall");
  39.     IfFound(nil);
  40.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  41.     Else(nil);
  42.         GSetPen(nil, C_TAN);
  43.         GAMove(nil, 16, 16);
  44.         GRectangle(nil, 129, 68, false);
  45.         GAMove(nil, 59, 32);
  46.         GRDraw(nil, 43, 0);
  47.         GRDraw(nil, 8, 8);
  48.         GRDraw(nil, 0, 20);
  49.         GRDraw(nil, -8, 8);
  50.         GRDraw(nil, -43, 0);
  51.         GRDraw(nil, -8, -8);
  52.         GRDraw(nil, 0, -20);
  53.         GRDraw(nil, 8, -8);
  54.         GRDraw(nil, 0, -16);
  55.         GAMove(nil, 102, 16);
  56.         GRDraw(nil, 0, 16);
  57.         GAMove(nil, 110, 40);
  58.         GRDraw(nil, 35, 0);
  59.         GAMove(nil, 110, 60);
  60.         GRDraw(nil, 35, 0);
  61.         GAMove(nil, 102, 68);
  62.         GRDraw(nil, 0, 16);
  63.         GAMove(nil, 59, 68);
  64.         GRDraw(nil, 0, 16);
  65.         GAMove(nil, 16, 60);
  66.         GRDraw(nil, 35, 0);
  67.         GAMove(nil, 16, 40);
  68.         GRDraw(nil, 35, 0);
  69.  
  70.         GSetPen(nil, C_BLACK);
  71.         GAMove(nil, 110, 41);
  72.         GRDraw(nil, 0, 18);
  73.         GAMove(nil, 145, 41);
  74.         GRDraw(nil, 0, 18);
  75.  
  76.         GSetPen(nil, C_BROWN);
  77.         GAMove(nil, 76, 32);
  78.         HorizontalDoor();
  79.         GAMove(nil, 76, 68);
  80.         HorizontalDoor();
  81.         GAMove(nil, 51, 46);
  82.         VerticalDoor();
  83.         GAMove(nil, 57, 34);
  84.         NorthWestDoor();
  85.         GAMove(nil, 53, 62);
  86.         NorthEastDoor();
  87.         GAMove(nil, 104, 34);
  88.         NorthEastDoor();
  89.         GAMove(nil, 108, 62);
  90.         NorthWestDoor();
  91.  
  92.         GSetPen(nil, C_GOLD);
  93.         GAMove(nil, 30, 31);
  94.         GText(nil, "GR");
  95.         GAMove(nil, 27, 53);
  96.         GText(nil, "LF");
  97.         GAMove(nil, 30, 75);
  98.         GText(nil, "BS");
  99.         GAMove(nil, 74, 27);
  100.         GText(nil, "MR");
  101.         GAMove(nil, 74, 53);
  102.         GText(nil, "MM");
  103.         GAMove(nil, 74, 79);
  104.         GText(nil, "ST");
  105.         GAMove(nil, 116, 31);
  106.         GText(nil, "AR");
  107.         GAMove(nil, 116, 75);
  108.         GText(nil, "BK");
  109.     Fi(nil);
  110.     
  111.     EndEffect();
  112.     fi;
  113.     CallEffect(nil, MINI_MALL_ID);
  114. corp;
  115.  
  116. define tp_mall MALL_MAP_GROUP NextMapGroup().
  117.  
  118. /*
  119.  * The mall entrance room has a bunch of direction specific descriptions and
  120.  * messages. It also contains the 'enter-exit machine', a bench to sit on,
  121.  * and a hidden exit under the plate in the floor.
  122.  */
  123.  
  124. define tp_mall r_underPlate CreateThing(r_indoors).    /* needed here */
  125.  
  126. /* r_mallEntrance is in tp_misc, since is used in other files */
  127. define tp_misc r_mallEntrance CreateThing(r_indoors).
  128. SetupRoom(r_mallEntrance, "in a small public passageway", "").
  129. r_mallEntrance@p_rWestDesc := "You can see back into the mini mall.".
  130. r_mallEntrance@p_rWestMessage := "You walk into the mini mall.".
  131. r_mallEntrance@p_rWestOMessage := "walks into the mini mall.".
  132. r_mallEntrance@p_rWestEMessage := "comes from the mini mall.".
  133. r_mallEntrance@p_rEastDesc := "You can see out towards the street.".
  134. r_mallEntrance@p_rEastMessage := "You walk out onto the sunny street.".
  135. r_mallEntrance@p_rEastOMessage := "walks out onto the street.".
  136. r_mallEntrance@p_rEastEMessage := "comes in from the street.".
  137. r_mallEntrance@p_rNoGoString := "You cannot walk through concrete.".
  138. RoomGraphics(r_mallEntrance, "Mall", "Entrance", MALL_MAP_GROUP, 124, 47,
  139.          drawMiniMall).
  140. define tp_mall o_bench CreateThing(nil).
  141. SetupObject(o_bench, r_mallEntrance, "bench;wooden",
  142.     "The bench is a bit faded, but quite usable. There is room for 3 people "
  143.     "to sit on it.").
  144. o_bench@p_oCanSitOn := 4.    /* one greater than actual capacity */
  145. o_bench@p_oNotGettable := true.
  146. FakeObject(CreateThing(nil), r_mallEntrance, "floor",
  147.     "There is a 3 foot square metal plate set into the floor. It looks like "
  148.     "it can be raised on its hinges.").
  149. r_mallEntrance@p_rDownDesc :=
  150.     "There is a 3 foot square metal plate set into the floor. It looks like "
  151.     "it can be raised on its hinges.".
  152. define tp_mall proc walkOnPlate()status:
  153.     Print("There is a metallic clanging sound as you get here.\n");
  154.     OPrint("Clang!\n");
  155.     /* walking on the plate can also be heard in the room under the plate */
  156.     ABPrint(r_underPlate, nil, nil, "Clang!\n");
  157.     continue
  158. corp;
  159. AddAnyEnterChecker(r_mallEntrance, walkOnPlate, false).
  160. /* We can operate on the plate from either above it or below it. So, we
  161.    define a generic one, and inherit from it for the ones that are in the
  162.    two rooms. */
  163. define tp_mall o_entrancePlate CreateThing(nil).
  164. FakeModel(o_entrancePlate,
  165.     "plate;metal.plate;dirty,metal,metallic,3,foot,square,hinged",
  166.     "The plate is quite battered, and sags slightly in the middle. There are "
  167.     "hinges on one side, and a small, recessed handle on the opposite side.").
  168. o_entrancePlate@p_oSmellString := "It smells like very dirty metal.".
  169. o_entrancePlate@p_oTouchString := "It feels like very dirty metal.".
  170. o_entrancePlate@p_oLowerString := "The plate cannot be lowered any further.".
  171. o_entrancePlate@p_oCloseString := "The plate is already closed.".
  172. o_entrancePlate@p_oNotLocked := true.
  173. define tp_mall o_entrancePlate1 CreateThing(o_entrancePlate).    /* inherit */
  174. SetThingStatus(o_entrancePlate1, ts_wizard).
  175. AddTail(r_mallEntrance@p_rContents, o_entrancePlate1).
  176. Scenery(r_mallEntrance, "hinge.handle;small,recessed").
  177. define tp_mall proc plateLift1()status:
  178.     Print("The plate lifts easily on its hinges. You see a metal ladder "
  179.     "leading down into a small space under the passageway. You climb down "
  180.     "the ladder, and the plate closes over you.\n");
  181.     if Me()@p_pHidden then
  182.     OPrint("The metal plate lifts for a moment, then closes.\n");
  183.     else
  184.     OPrint(FormatName(Me()@p_pName) +
  185.         " lifts the metal plate in the floor and descends beneath it.\n");
  186.     fi;
  187.     LeaveRoomStuff(r_underPlate, D_DOWN, MOVE_SPECIAL);
  188.     EnterRoomStuff(r_underPlate, D_UP, MOVE_NORMAL);
  189.     succeed
  190. corp;
  191. o_entrancePlate1@p_oLiftChecker := plateLift1.
  192. o_entrancePlate1@p_oOpenChecker := plateLift1.
  193.  
  194. /* Exercise for the reader: make the plate have an open/closed state, so that
  195.    the player must open the plate, then go down. You should use functions
  196.    dependent on its state for all relevant descriptions, actions, etc. Don't
  197.    forget all the stuff later on for the other side of the plate! */
  198.  
  199. /* For the central area of the minimall, there is not much, but we continue
  200.    with the direction messages for the mall entrance. */
  201.  
  202. define tp_mall r_miniMall CreateThing(r_indoors).
  203. SetupRoom(r_miniMall, "in the mini mall",
  204.     "This is a small shopping area which collects together a number of useful "
  205.     "services. The seven individual areas are distributed around the sides "
  206.     "of the mall, and a passageway to the street is to the east.").
  207. Connect(r_mallEntrance, r_miniMall, D_WEST).
  208. Connect(r_mallEntrance, r_miniMall, D_ENTER).
  209. r_miniMall@p_rEastDesc :=
  210.     "A large, gloomy passageway heads to the east. You can see something on "
  211.     "the floor half-way through, and daylight at the far end.".
  212. r_miniMall@p_rEastMessage := "You head into the passageway.".
  213. r_miniMall@p_rEastOMessage := "heads into the passageway.".
  214. r_miniMall@p_rEastEMessage := "arrives from the passageway.".
  215. r_miniMall@p_rExitDesc :=
  216.     "A large, gloomy passageway heads to the east. You can see something on "
  217.     "the floor half-way through, and daylight at the far end.".
  218. r_miniMall@p_rExitMessage := "You head into the passageway.".
  219. r_miniMall@p_rExitOMessage := "heads into the passageway.".
  220. RoomGraphics(r_miniMall, "Mini", "Mall", MALL_MAP_GROUP, 78, 47, drawMiniMall).
  221.  
  222. /* SysAdmin's study is a hidden room, and it's graphic is a random set of
  223.    coloured rectangles (likely different each time). */
  224.  
  225. define tp_mall r_SysAdminsStudy CreateThing(r_indoors).
  226. SetupRoom(r_SysAdminsStudy, "in SysAdmin's study",
  227.     "The mini mall is magically below you.").
  228. define tp_mall proc drawStudy()void:
  229.     int i, x, y;
  230.  
  231.     for i from 1 upto Random(20) + 10 do
  232.     GSetPen(nil, Random(32));
  233.     x := Random(159);
  234.     y := Random(99);
  235.     GAMove(nil, x, y);
  236.     GRectangle(nil, Random(160 - x), Random(100 - x), true);
  237.     od;
  238.     /* force a re-draw on look */
  239.     Me()@p_MapGroup := UNKNOWN_MAP_GROUP;
  240. corp;
  241. RoomGraphics(r_SysAdminsStudy, "SysAdmin's", "Study", NextMapGroup(), 0, 0,
  242.          drawStudy).
  243. HConnect(r_miniMall, r_SysAdminsStudy, D_UP).
  244. HConnect(r_SysAdminsStudy, r_miniMall, D_DOWN).
  245. define tp_mall m_watcher CreateThing(nil).
  246. CreateMachine("", m_watcher, r_miniMall, nil).
  247. define tp_mall proc watchHandler(string message)void:
  248.     SetPrefix("MM: ");
  249.     /* this is dangerous! */
  250.     ABPrint(r_SysAdminsStudy, nil, nil, message);
  251.     SetPrefix("");
  252. corp;
  253. ignore SetMachineOther(m_watcher, watchHandler).
  254.  
  255. /* arrivals room is created in util.m */
  256. Connect(r_miniMall, r_arrivals, D_NORTHEAST).
  257. UniConnect(r_arrivals, r_miniMall, D_EXIT).
  258. r_arrivals@p_rNoGoString := "You must go through the doors.".
  259. RoomGraphics(r_arrivals, "Arrivals", "Room", MALL_MAP_GROUP, 120, 25,
  260.          drawMiniMall).
  261.  
  262. /* The actual mail service is defined later, in 'mail.m' */
  263.  
  264. /* r_mailRoom is in tp_misc, since it is needed in other files */
  265. define tp_misc r_mailRoom CreateThing(r_indoors).
  266. SetupRoom(r_mailRoom, "in the mail room",
  267.     "This room looks much like all mail rooms. A bank of little "
  268.     "lockable boxes fills one wall. Another is filled by a long counter, "
  269.     "which has a couple of service positions screened with metal bars. "
  270.     "You can REGISTER at the wickets to send and receive mail, and you can "
  271.     "come here to read any mail that people have sent you.").
  272. Connect(r_miniMall, r_mailRoom, D_NORTH).
  273. UniConnect(r_mailRoom, r_miniMall, D_EXIT).
  274. r_mailRoom@p_rNoGoString := "You must go through the doors.".
  275. RoomGraphics(r_mailRoom, "Mail", "Room", MALL_MAP_GROUP, 78, 21, drawMiniMall).
  276. Scenery(r_mailRoom,
  277.     "bank.boxes,box;bank,of,little,lockable.lock."
  278.     "counter;long."
  279.     "position,wicket;service."
  280.     "bar;metal").
  281.  
  282. /*
  283.  * The garbage room. If you drop something you own here, it is destroyed.
  284.  * There is also a slightly persistent bad smell - shows the use of attaching
  285.  * verb-specific stuff to the the player.
  286.  */
  287.  
  288. /* r_garbageRoom is in tp_misc since it is needed in other files */
  289. define tp_misc r_garbageRoom CreateThing(r_indoors).
  290. SetupRoom(r_garbageRoom, "in the garbage room",
  291.     "Drop things here to dispose of them.").
  292. Connect(r_miniMall, r_garbageRoom, D_NORTHWEST).
  293. UniConnect(r_garbageRoom, r_miniMall, D_EXIT).
  294. /* NOTE: not 'utility' - we want to be able to ClearThing the stuff */
  295. define tp_mall proc garbageDrop(thing th)status:
  296.     thing carryer;
  297.     string name;
  298.  
  299.     if Owner(th) = SysAdmin then
  300.     carryer := th@p_oCarryer;
  301.     if carryer ~= nil then
  302.         if th@p_oCreator = Me() or th@p_oCreator = CharacterThing(SysAdmin)
  303.         then
  304.         name := FormatName(th@p_oName);
  305.         ZapObject(th);
  306.         if not carryer@p_pHidden then
  307.             ABPrint(r_garbageRoom, carryer, carryer,
  308.             FormatName(carryer@p_pName) + AAn(" drops", name) +
  309.             " which vanishes!\n");
  310.         else
  311.             ABPrint(r_garbageRoom, carryer, carryer,
  312.             Capitalize(AAn("", name)) +
  313.             " appears, drops, and vanishes!\n");
  314.         fi;
  315.         SPrint(carryer, "You drop the " + name + " which vanishes!\n");
  316.         DelElement(carryer@p_pCarrying, th);
  317.         /* we do NOT want to continue with the normal drop actions */
  318.         succeed
  319.         else
  320.         continue
  321.         fi
  322.     else
  323.         continue
  324.     fi
  325.     else
  326.     continue
  327.     fi
  328. corp;
  329. AddRoomDropChecker(r_garbageRoom, garbageDrop, false).
  330. define tp_mall proc garbageSmellDisable()status:
  331.     Print("Your nose is still disabled!\n");
  332.     if Here() ~= r_garbageRoom then
  333.     Me() -- p_oSmellChecker;
  334.     fi;
  335.     succeed
  336. corp;
  337. define tp_mall proc garbageSmell()status:
  338.     if It() = nil then
  339.     Print("This room smells distinctly like a garbage room!\n");
  340.     else
  341.     Print("You can't smell the ");
  342.     Print(FormatName(It()@p_oName));
  343.     Print(" over the smell of this room!\n");
  344.     fi;
  345.     Me()@p_oSmellChecker := garbageSmellDisable;
  346.     succeed
  347. corp;
  348. r_garbageRoom@p_oSmellChecker := garbageSmell.
  349. r_garbageRoom@p_rNoGoString := "You must go through the doors.".
  350. RoomGraphics(r_garbageRoom, "Garbage", "Room", MALL_MAP_GROUP, 34, 25,
  351.          drawMiniMall).
  352.  
  353. /* lost and found room is created in util.m */
  354. Connect(r_miniMall, r_lostAndFound, D_WEST).
  355. UniConnect(r_lostAndFound, r_miniMall, D_EXIT).
  356. r_lostAndFound@p_rNoGoString := "You must go through the doors.".
  357. RoomGraphics(r_lostAndFound, "Lost & Found", "Room", MALL_MAP_GROUP, 31, 47,
  358.          drawMiniMall).
  359.  
  360. /*
  361.  * The beauty shop allows a number of additional activities. Non-graphics
  362.  * players can REGISTER to change their description. Graphics players are given
  363.  * a couple of extra on-screen buttons, which call up the icon editor in
  364.  * 'graphics.m' to edit their icon or cursor. A third button allows editing
  365.  * their description via the remote client. There is also use of the voice
  366.  * synthesis when you enter the room, or re-enter the game when in it.
  367.  */
  368.  
  369. define tp_mall ICON_BUTTON    100.
  370. define tp_mall CURSOR_BUTTON    101.
  371. define tp_mall DESC_BUTTON    102.
  372. define tp_mall BEAUTY_SPEECH_ID NextSoundEffectId().
  373. define tp_mall proc addBeautyButtons()void:
  374.     AddButton(166, 83, ICON_BUTTON, "Icon");
  375.     AddButton(212, 83, CURSOR_BUTTON, "Cursor");
  376.     AddButton(273, 83, DESC_BUTTON, "Desc");
  377.     Me()@p_pStandardButtonsNow := false;
  378. corp;
  379. define tp_mall proc eraseBeautyButtons()void:
  380.     EraseButton(ICON_BUTTON);
  381.     EraseButton(CURSOR_BUTTON);
  382.     EraseButton(DESC_BUTTON);
  383.     Me()@p_pStandardButtonsNow := true;
  384.     AbortEffect(nil, EFFECT_SPEECH, BEAUTY_SPEECH_ID);
  385. corp;
  386. define tp_mall proc beautySpeak()void:
  387.     /* if voice is not on, will not do this */
  388.     VParams(nil, 160, 250, 0, 1, 64);
  389.     VNarrate(nil,
  390.     "GUH4D DEY3. REHJIHSTER TUW CHEY1NCH YOHR DIYSKRIH1PSHUN.",
  391.     BEAUTY_SPEECH_ID);
  392.     VReset(nil);
  393. corp;
  394. define tp_mall r_beautyShop CreateThing(r_indoors).
  395. SetupRoom(r_beautyShop, "in the beauty shop",
  396.     "You can REGISTER here to have your appearance changed.").
  397. define tp_mall proc utility beautyEnd(string s)void:
  398.     string name;
  399.     thing me;
  400.  
  401.     if s = "" then
  402.     Print("Description not changed.\n");
  403.     else
  404.     me := Me();
  405.     name := FormatName(me@p_pName);
  406.     OPrint(name + " has just been made over.\n");
  407.     s := name + " " + s;
  408.     me@p_pDesc := s;
  409.     Print("Nip! Tuck! Snip-snip! All done. "
  410.         "When people look at you now, they will see:\n"
  411.     );
  412.     /* note the use of NPrint! */
  413.     NPrint(s + "\n");
  414.     fi;
  415.     if Here() = r_beautyShop then
  416.     addBeautyButtons();
  417.     fi;
  418. corp;
  419. /* this is not 'utility' so that we don't get '@'s on the output */
  420. define tp_mall proc beautyRegister()bool:
  421.     thing me;
  422.     string name;
  423.     int len;
  424.     bool res;
  425.  
  426.     me := Me();
  427.     name := me@p_pName;
  428.     OPrint(FormatName(name) + " decides to get a makeover.\n");
  429.     len := Length(name) + 1;
  430.     name := me@p_pDesc;
  431.     name := SubString(name, len, Length(name) - len);
  432.     res := GetDocument("beauty> ", "Enter your new description", name,
  433.                beautyEnd, false);
  434.     if not res then
  435.     addBeautyButtons();
  436.     fi;
  437.     res
  438. corp;
  439. r_beautyShop@p_rRegisterAction := beautyRegister.
  440. Connect(r_miniMall, r_beautyShop, D_SOUTHWEST).
  441. UniConnect(r_beautyShop, r_miniMall, D_EXIT).
  442. r_beautyShop@p_rNoGoString := "You must go through the doors.".
  443. RoomGraphics(r_beautyShop, "Beauty", "Shop", MALL_MAP_GROUP, 34, 69,
  444.          drawMiniMall).
  445. define tp_mall p_pBeautyHandlerSave CreateActionProp().
  446. define tp_mall p_pBeautyActiveSave CreateActionProp().
  447. define tp_mall proc beautyReset()void:
  448.     thing me;
  449.     action a;
  450.  
  451.     me := Me();
  452.     a := me@p_pBeautyActiveSave;
  453.     if a ~= nil then
  454.     eraseBeautyButtons();
  455.     ignore SetCharacterActiveAction(a);
  456.     me -- p_pBeautyActiveSave;
  457.     ignore SetCharacterButtonAction(me@p_pBeautyHandlerSave);
  458.     me -- p_pBeautyHandlerSave;
  459.     fi;
  460. corp;
  461. define tp_mall proc beautyRestore()void:
  462.     Me()@p_MapGroup := NO_MAP_GROUP;
  463.     EnterRoomDraw();
  464.     if Here() ~= r_beautyShop then
  465.     beautyReset();
  466.     else
  467.     addBeautyButtons();
  468.     fi;
  469. corp;
  470. define tp_mall proc beautyButtonHandler(int whichButton)void:
  471.     action a;
  472.  
  473.     if whichButton = ICON_BUTTON then
  474.     eraseBeautyButtons();
  475.     StartIconEdit(beautyRestore);
  476.     elif whichButton = CURSOR_BUTTON then
  477.     eraseBeautyButtons();
  478.     StartCursorEdit(beautyRestore);
  479.     elif whichButton = DESC_BUTTON then
  480.     eraseBeautyButtons();
  481.     ignore beautyRegister();
  482.     else
  483.     a := Me()@p_pBeautyHandlerSave;
  484.     if a ~= nil then
  485.         call(a, void)(whichButton);
  486.     fi;
  487.     fi;
  488. corp;
  489. define tp_mall proc beautyActiveHandler()void:
  490.     action a;
  491.  
  492.     a := Me()@p_pBeautyActiveSave;
  493.     if a ~= nil then
  494.     call(a, void)();
  495.     fi;
  496.     /* if graphics is not on, will not do the buttons */
  497.     addBeautyButtons();
  498.     a := SetCharacterButtonAction(beautyButtonHandler);
  499.     if a ~= nil then
  500.     Me()@p_pBeautyHandlerSave := a;
  501.     fi;
  502.     beautySpeak();
  503. corp;
  504. define tp_mall proc beautyEnter()status:
  505.     action a;
  506.     thing me;
  507.  
  508.     me := Me();
  509.     if me@p_pStandardButtonsNow then
  510.     if not Editing() then
  511.         addBeautyButtons();
  512.     fi;
  513.     a := SetCharacterButtonAction(beautyButtonHandler);
  514.     if a ~= nil then
  515.         me@p_pBeautyHandlerSave := a;
  516.     fi;
  517.     a := SetCharacterActiveAction(beautyActiveHandler);
  518.     if a ~= nil then
  519.         me@p_pBeautyActiveSave := a;
  520.     fi;
  521.     fi;
  522.     beautySpeak();
  523.     continue
  524. corp;
  525. define tp_mall proc beautyExit()status:
  526.     beautyReset();
  527.     continue
  528. corp;
  529. AddAnyEnterChecker(r_beautyShop, beautyEnter, false).
  530. AddAnyLeaveChecker(r_beautyShop, beautyExit, false).
  531.  
  532. /*
  533.  * The store in the mall has a number of items for sale. The fanciest is
  534.  * the camera. Also note the universal carryall, which is a container with
  535.  * no restrictions on what you can put into it.
  536.  */
  537.  
  538. define tp_mall r_mallStore CreateThing(r_indoors).
  539. SetupRoom(r_mallStore, "in a small store",
  540.     "You can SHOP for supplies here.").
  541. ignore AddForSale(r_mallStore, "pen;ballpoint.pen;ball,point",
  542.     "There is nothing special about the ballpoint pen. It will "
  543.     "provide a lifetime of trouble-free writing.",
  544.     1, nil).
  545. ignore AddForSale(r_mallStore, "pad,paper;writing.paper;pad,of",
  546.     "The writing pad is quite ordinary. It provides an "
  547.     "infinite supply of sheets to write on.",
  548.     1, nil).
  549. define tp_mall o_carryall AddForSale(r_mallStore, "carryall;universal",
  550.     "The universal carryall is a somewhat magical item. You can put as much "
  551.     "stuff, of any size and shape, as you want into it.",
  552.     1000, nil).
  553. o_carryall@p_oContents := CreateThingList().
  554. o_carryall@p_oCapacity := 1000000.
  555.  
  556. define tp_mall o_lamp AddForSale(r_mallStore,
  557.     "lamp;everlight.switch;push-button,push,button,on-off,on,off",
  558.     "The everlight lamp is a small ovoid made of some indeterminate material. "
  559.     "It has an opening on the front through which soft white light is "
  560.     "emitted. There seems to be no identifiable power source. There is a "
  561.     "push-button on-off switch in the middle of it.",
  562.     5000, nil).
  563. o_lamp@p_oActivateChecker := ActiveLightObject.
  564. o_lamp@p_oLightChecker := ActiveLightObject.
  565. o_lamp@p_oDeActivateChecker := ActiveUnLightObject.
  566. o_lamp@p_oExtinguishChecker := ActiveUnLightObject.
  567. define tp_mall proc lampPutIn(thing lamp, container)status:
  568.     if lamp@p_oLight then
  569.     lamp@p_oLight := false;
  570.     RemoveLight();
  571.     lamp@p_oLight := true;
  572.     fi;
  573.     continue
  574. corp;
  575. o_lamp@p_oPutMeInChecker := lampPutIn.
  576. define tp_mall proc lampTakeFrom(thing lamp, container)status:
  577.     if lamp@p_oLight then
  578.     AddLight();
  579.     fi;
  580.     continue
  581. corp;
  582. o_lamp@p_oTakeMeFromChecker := lampTakeFrom.
  583.  
  584. define tp_mall p_oShotsLeft CreateIntProp().
  585. define tp_mall proc cameraBuy()status:
  586.     It()@p_oShotsLeft := 12;
  587.     continue
  588. corp;
  589. define tp_mall proc cameraDesc()string:
  590.     int n;
  591.  
  592.     n := It()@p_oShotsLeft;
  593.     "The instant camera is an ugly box-like contraption with a small lens on "
  594.     "one side and a big slot for the pictures at the bottom. There is a "
  595.     "flash attachment on top. It appears to be quite functional. "
  596.     "You can use it with the 'photograph' or 'snap' commands. "
  597.     "You can take pictures of the current location, of objects, or of "
  598.     "people/animals. The little indicator shows that the camera has " +
  599.     if n = 1 then
  600.         "one shot"
  601.     elif n = 0 then
  602.         "no shots"
  603.     else
  604.         IntToString(n) + " shots"
  605.     fi +
  606.     " left."
  607. corp;
  608. define tp_mall o_camera AddForSale(r_mallStore, "camera;instant", "", 50,
  609.     cameraBuy).
  610. o_camera@p_oDescAction := cameraDesc.
  611. MakeStore(r_mallStore).
  612. Connect(r_miniMall, r_mallStore, D_SOUTH).
  613. UniConnect(r_mallStore, r_miniMall, D_EXIT).
  614. r_mallStore@p_rNoGoString := "You must go through the doors.".
  615. RoomGraphics(r_mallStore, "Small", "Store", MALL_MAP_GROUP, 78, 73,
  616.          drawMiniMall).
  617.  
  618. /*
  619.  * Code to implement photographs and photography. This code should really
  620.  * go elsewhere, but I'm not sure where.
  621.  */
  622.  
  623. /* o_photograph is in tp_misc since it is used in bguild.m */
  624. define tp_misc o_photograph CreateThing(nil).
  625. o_photograph@p_oHome := r_garbageRoom.
  626. define tp_mall proc createPhotograph(string name, desc)thing:
  627.     string noun, adj;
  628.     thing photo, me;
  629.     int i;
  630.  
  631.     if name = "" then
  632.     name := "photograph.photo.picture.snapshot";
  633.     else
  634.     name := FormatName(name);
  635.     name := GetNounPhrase(G, name, 0);
  636.     i := Index(name, ";");
  637.     if i = -1 then
  638.         name := name + ";photograph,of." + name + ";photo,of." +
  639.             name + ";picture,of." + name + ";snapshot,of." +
  640.             "photograph.photo.picture.snapshot";
  641.     else
  642.         noun := SubString(name, 0, i);
  643.         adj := SubString(name, i + 1, Length(name) - i - 1);
  644.         name := noun + ";photograph,of," + adj + "." +
  645.             noun + ";picture,of," + adj + "." +
  646.             noun + ";photo,of," + adj + "." +
  647.             noun + ";snapshot,of," + adj +
  648.             ".photograph.photo.picture.snapshot";
  649.     fi;
  650.     fi;
  651.     me := Me();
  652.     Print("Click - FLASH!!\n");
  653.     OPrint("FLASH! - " + FormatName(me@p_pName) + " takes a photograph.\n");
  654.     photo := CreateThing(o_photograph);
  655.     photo@p_oCarryer := me;
  656.     photo@p_oCreator := me;
  657.     photo@p_oName := name;
  658.     photo@p_oDesc := desc;
  659.     SetThingStatus(photo, ts_public);
  660.     GiveThing(photo, SysAdmin);
  661.     AddTail(me@p_pCarrying, photo);
  662.     photo
  663. corp;
  664.  
  665. define tp_mall proc v_photograph(string what)bool:
  666.     thing here, camera, object;
  667.     action a;
  668.     string name, desc, ambig, read;
  669.     int count, dir;
  670.     status st;
  671.     bool wasScenery;
  672.  
  673.     here := Here();
  674.     if FindChildOnList(Me()@p_pCarrying, o_camera) then
  675.     camera := FindResult();
  676.     count := camera@p_oShotsLeft;
  677.     if count = 0 then
  678.         Print("The camera has no shots left.\n");
  679.         false
  680.     elif what = "" then
  681.         /* taking a picture of the current location */
  682.         a := here@p_rNameAction;
  683.         if a ~= nil then
  684.         name := call(a, string)();
  685.         else
  686.         name := here@p_rName;
  687.         fi;
  688.         name := name + ".";
  689.         a := here@p_rDescAction;
  690.         if a ~= nil then
  691.         name := name + "\n";
  692.         desc := call(a, string)();
  693.         elif here@p_rDesc ~= "" then
  694.         name := name + "\n";
  695.         desc := here@p_rDesc;
  696.         else
  697.         desc := "";
  698.         fi;
  699.         camera@p_oShotsLeft := count - 1;
  700.         ignore createPhotograph("",
  701.         "This photograph was taken " + name + desc);
  702.         true
  703.     else
  704.         object := FindAgent(what);
  705.         if object ~= nil then
  706.         a := object@p_pDescAction;
  707.         if a ~= nil then
  708.             SetIt(object);
  709.             desc := call(a, string)();
  710.         elif object@p_pDesc ~= "" then
  711.             desc := object@p_pDesc;
  712.         else
  713.             desc := name + "is a nondescript adventurer.";
  714.         fi;
  715.         camera@p_oShotsLeft := count - 1;
  716.         ignore createPhotograph(object@p_pName, desc);
  717.         true
  718.         else
  719.         dir := DirMatch(what);
  720.         if dir ~= -1 then
  721.             desc := here@(DirDesc(dir));
  722.             if desc = "" then
  723.             desc := "The photograph shows nothing special.";
  724.             else
  725.             desc := desc;
  726.             fi;
  727.             camera@p_oShotsLeft := count - 1;
  728.             ignore createPhotograph("", desc);
  729.             true
  730.         else
  731.             /* player is photographing an object */
  732.             name := FormatName(what);
  733.             object := nil;
  734.             wasScenery := false;
  735.             ambig := " is ambiguous here.\n";
  736.             st := FindName(Me()@p_pCarrying, p_oName, what);
  737.             if st = fail then
  738.             st := FindName(here@p_rContents, p_oName, what);
  739.             if st = fail then
  740.                 if MatchName(here@p_rScenery, what) ~= -1 then
  741.                 wasScenery := true;
  742.                 else
  743.                 Print(IsAre("There", "no", name, "here.\n"));
  744.                 fi;
  745.             elif st = continue then
  746.                 Print(name);
  747.                 Print(ambig);
  748.             else
  749.                 object := FindResult();
  750.             fi;
  751.             elif st = continue then
  752.             Print(name);
  753.             Print(ambig);
  754.             else
  755.             object := FindResult();
  756.             fi;
  757.             if object = nil then
  758.             if wasScenery then
  759.                 camera@p_oShotsLeft := count - 1;
  760.                 ignore createPhotograph(what,
  761.                 "The photograph shows nothing special.");
  762.                 true
  763.             else
  764.                 false
  765.             fi
  766.             elif object = camera then
  767.             Print("No matter how you twist or turn it, you "
  768.                 "cannot get the camera to take a picture of "
  769.                 "itself.\n");
  770.             false
  771.             else
  772.             a := object@p_oDescAction;
  773.             if a ~= nil then
  774.                 SetIt(object);
  775.                 desc := call(a, string)();
  776.             elif object@p_oDesc ~= "" then
  777.                 desc := object@p_oDesc;
  778.             else
  779.                 desc := "The photograph shows nothing special.";
  780.             fi;
  781.             a := object@p_oReadAction;
  782.             if a ~= nil then
  783.                 read := call(a, string)();
  784.             elif object@p_oReadString ~= "" then
  785.                 read := object@p_oReadString;
  786.             else
  787.                 read := "";
  788.             fi;
  789.             camera@p_oShotsLeft := count - 1;
  790.             object := createPhotograph(what, desc);
  791.             if read ~= "" then
  792.                 object@p_oReadString := read;
  793.             fi;
  794.             true
  795.             fi
  796.         fi
  797.         fi
  798.     fi
  799.     else
  800.     Print("You don't have a camera!\n");
  801.     false
  802.     fi
  803. corp;
  804.  
  805. Verb1(G, "photograph", 0, v_photograph).
  806. Synonym(G, "photograph", "photo").
  807. Synonym(G, "photograph", "snap").
  808.  
  809. /*
  810.  * The bank in the minimall uses the bank code from 'util.m', and uses
  811.  * speech when you enter it.
  812.  */
  813.  
  814. define tp_mall BANK_SPEECH_ID NextSoundEffectId().
  815. define tp_mall r_mallBank CreateThing(r_indoors).
  816. SetupRoom(r_mallBank, "in a small local bank",
  817.     "You can use the commands 'deposit <amount>', 'withdraw <amount>' and "
  818.     "'balance' here.").
  819. Connect(r_miniMall, r_mallBank, D_SOUTHEAST).
  820. UniConnect(r_mallBank, r_miniMall, D_EXIT).
  821. MakeBank(r_mallBank).
  822. r_mallBank@p_rNoGoString := "You must go through the doors.".
  823. RoomGraphics(r_mallBank, "Bank", "", MALL_MAP_GROUP, 120, 69, drawMiniMall).
  824. define tp_mall proc bankSay()status:
  825.     if VOn(nil) then
  826.     VParams(nil, 150, 120, 0, 0, 64);
  827.     VNarrate(nil,
  828.         "WEH5LKAHM KAH4STAHMER. DIH4PAAZIHT MAH4NIY TUWDEY1.",
  829.         BANK_SPEECH_ID);
  830.     VReset(nil);
  831.     fi;
  832.     continue
  833. corp;
  834. AddAnyEnterChecker(r_mallBank, bankSay, false).
  835. define tp_mall proc bankExit()status:
  836.     if VOn(nil) then
  837.     AbortEffect(nil, EFFECT_SPEECH, BANK_SPEECH_ID);
  838.     fi;
  839.     continue
  840. corp;
  841. AddAnyLeaveChecker(r_mallBank, bankExit, false).
  842.  
  843. /*
  844.  * The service tunnels under the plate in the mall entrance are mostly
  845.  * description and scenery, although there is a door to open, and you get
  846.  * 100 blutos at the far end.
  847.  */
  848.  
  849. /* actual room thing created earlier */
  850.  
  851. SetupRoom(r_underPlate, "in a small, cramped space under the passageway",
  852.     "Immediately over your head is a metal plate which can be lifted to "
  853.     "allow you to exit. The walls of this chamber are of stained concrete "
  854.     "blocks. The floor is of cracked, dirty concrete. A round shaft heads "
  855.     "down into darkness. There are rusty metal wrungs embedded in one side "
  856.     "of the shaft.").
  857. Scenery(r_underPlate,
  858.     "floor,concrete;cracked,dirty,concrete,of."
  859.     "wall,block;stained,concrete,block."
  860.     "shaft;round."
  861.     "wrung;rusty,metal."
  862.     "hinge."
  863.     "handle;small,recessed").
  864. AutoGraphics(r_underPlate, AutoTunnels).
  865. AutoPens(r_underPlate, C_DARK_BROWN, C_LIGHT_GREY, 0, 0).
  866. define tp_mall o_entrancePlate2 CreateThing(o_entrancePlate).    /* inherit */
  867. SetThingStatus(o_entrancePlate2, ts_wizard).
  868. AddTail(r_underPlate@p_rContents, o_entrancePlate2).
  869. define tp_mall proc plateLift3()status:
  870.     Print("You lift the plate, climb up to the passageway, and lower the "
  871.     "plate back into place.\n");
  872.     LeaveRoomStuff(r_mallEntrance, D_UP, MOVE_NORMAL);
  873.     EnterRoomStuff(r_mallEntrance, D_DOWN, MOVE_SPECIAL);
  874.     if Me()@p_pHidden then
  875.     OPrint("The metal plate in the floor lifts up,"
  876.         " then lowers back into place.\n");
  877.     else
  878.     OPrint("The metal plate in the floor lifts up and " +
  879.         FormatName(Me()@p_pName) +
  880.         " emerges and lowers the plate back into place.\n");
  881.     fi;
  882.     succeed
  883. corp;
  884. o_entrancePlate2@p_oLiftChecker := plateLift3.
  885. o_entrancePlate2@p_oOpenChecker := plateLift3.
  886.  
  887. define tp_mall r_underMall CreateThing(r_indoors).
  888. SetThingStatus(r_underMall, ts_readonly).
  889. AutoGraphics(r_underMall, AutoTunnels).
  890. AutoPens(r_underMall, C_DARK_BROWN, C_LIGHT_GREY, 0, 0).
  891.  
  892. define tp_mall r_underMall1 CreateThing(r_underMall).
  893. SetupRoomD(r_underMall1, "at the end of a passageway",
  894.     "A low, narrow passageway from the northwest ends here. A round shaft "
  895.     "with metal wrungs on one side leads upward.").
  896. Connect(r_underPlate, r_underMall1, D_DOWN).
  897. Scenery(r_underMall1, "shaft;round.wrung;rusty,metal").
  898.  
  899. define tp_mall r_underMall2 CreateThing(r_underMall).
  900. SetupRoomD(r_underMall2, "at a corner in a passageway", "").
  901. Connect(r_underMall1, r_underMall2, D_NORTHWEST).
  902.  
  903. define tp_mall r_underMall3 CreateThing(r_underMall).
  904. SetupRoomD(r_underMall3, "at the end of a passageway",
  905.     "The passage extends to the east, and a steep staircase leads downwards.").
  906. Connect(r_underMall2, r_underMall3, D_WEST).
  907. Scenery(r_underMall3, "stair,staircase;steep").
  908.  
  909. define tp_mall r_underMall5 CreateThing(r_indoors).
  910. define tp_mall UTILITY_TUNNEL_ID NextEffectId().
  911. define tp_mall proc drawUtilityTunnel()void:
  912.  
  913.     if not KnowsEffect(nil, UTILITY_TUNNEL_ID) then
  914.     DefineEffect(nil, UTILITY_TUNNEL_ID);
  915.     GSetImage(nil, "utilityTunnel");
  916.     IfFound(nil);
  917.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  918.     Else(nil);
  919.         GSetPen(nil, C_DARK_BROWN);
  920.         GAMove(nil, 0, 0);
  921.         GRectangle(nil, 159, 99, true);
  922.         GSetPen(nil, C_LIGHT_GREY);
  923.         GAMove(nil, 65, 0);
  924.         GRectangle(nil, 30, 99, true);
  925.         GSetPen(nil, C_RED_ORANGE);
  926.         GAMove(nil, 97, 0);
  927.         GRectangle(nil, 1, 99, true);
  928.         GSetPen(nil, C_DARK_GREEN);
  929.         GAMove(nil, 62, 0);
  930.         GRectangle(nil, 1, 99, true);
  931.         GSetPen(nil, C_BLUE);
  932.         GAMove(nil, 60, 0);
  933.         GRectangle(nil, 1, 99, true);
  934.         GSetPen(nil, C_CADMIUM_YELLOW);
  935.         GAMove(nil, 100, 0);
  936.         GRDraw(nil, 0, 99);
  937.         GAMove(nil, 102, 0);
  938.         GRDraw(nil, 0, 99);
  939.     Fi(nil);
  940.     EndEffect();
  941.     fi;
  942.     CallEffect(nil, UTILITY_TUNNEL_ID);
  943. corp;
  944.  
  945. define tp_mall r_underMall4 CreateThing(r_indoors).
  946. SetupRoomD(r_underMall4, "at the bottom of some steep stairs",
  947.     "The stairs head up to the east, but the west is blocked by a heavy "
  948.     "metal door. The door has a sign reading \"Authorized Personnel Only\", "
  949.     "but it does not appear to be locked.").
  950. Connect(r_underMall3, r_underMall4, D_DOWN).
  951. Connect(r_underMall3, r_underMall4, D_WEST).
  952. Sign(r_underMall4, "sign;security,door",
  953.     "The sign is red with white lettering, and is firmly attached to the "
  954.     "door.",
  955.     "\"Authorized Personnel Only\"").
  956. define tp_mall o_securityDoor CreateThing(nil).
  957. FakeModel(o_securityDoor, "door;heavy,metal,security",
  958.     "The door is painted grey, but many scratches and dents show the metal "
  959.     "underneath.").
  960. o_securityDoor@p_oCloseString := "The door is already open.".
  961. o_securityDoor@p_oNotLocked := true.
  962. define tp_mall o_securityDoor1 CreateThing(o_securityDoor).
  963. AddTail(r_underMall4@p_rContents, o_securityDoor1).
  964. o_securityDoor1@p_oListenString :=
  965.     "You hear machine-like noises coming through the door.".
  966. define tp_mall proc openSecurityDoor1()status:
  967.     Print("You open the door and pass through. As you do, you are hit with a "
  968.     "blast of warm air, light and noise.\n");
  969.     ignore EnterRoom(r_underMall5, D_WEST, MOVE_NORMAL);
  970.     succeed
  971. corp;
  972. o_securityDoor1@p_oOpenChecker := openSecurityDoor1.
  973. define tp_mall SECURITY_DOOR_ID NextEffectId().
  974. define tp_mall proc drawOutsideDoor()void:
  975.  
  976.     if not KnowsEffect(nil, SECURITY_DOOR_ID) then
  977.     DefineEffect(nil, SECURITY_DOOR_ID);
  978.     GSetImage(nil, "securityDoor");
  979.     IfFound(nil);
  980.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  981.     Else(nil);
  982.         GSetPen(nil, C_DARK_BROWN);
  983.         GAMove(nil, 0, 0);
  984.         GRectangle(nil, 159, 99, true);
  985.         GSetPen(nil, C_LIGHT_GREY);
  986.         GAMove(nil, 66, 41);
  987.         GRectangle(nil, 93, 18, true);
  988.         GSetPen(nil, C_DARK_GREY);
  989.         GAMove(nil, 66, 46);
  990.         VerticalDoor();
  991.     Fi(nil);
  992.     EndEffect();
  993.     fi;
  994.     CallEffect(nil, SECURITY_DOOR_ID);
  995. corp;
  996. AutoGraphics(r_underMall4, drawOutsideDoor).
  997.  
  998. SetupRoom(r_underMall5, "in a pit in the tunnel floor",
  999.     "Above you is the metal floor of the utility tunnel. Steep metal stairs "
  1000.     "lead up to a trapdoor in the floor. To your east is a metal security "
  1001.     "door.").
  1002. define tp_mall o_securityDoor2 CreateThing(o_securityDoor).
  1003. AddTail(r_underMall5@p_rContents, o_securityDoor2).
  1004. define tp_mall proc openSecurityDoor2()status:
  1005.     Print("You open the door and pass through.\n");
  1006.     ignore EnterRoom(r_underMall4, D_EAST, MOVE_NORMAL);
  1007.     succeed
  1008. corp;
  1009. o_securityDoor2@p_oOpenChecker := openSecurityDoor2.
  1010. Scenery(r_underMall5, "stair,floor,grill;steep,metal.grillwork;metal").
  1011. define tp_mall o_trapDoor CreateThing(nil).
  1012. FakeObject(o_trapDoor, r_underMall5, "door;trap.trapdoor", "").
  1013. o_trapDoor@p_oOpenString := "The trapdoor is already open.".
  1014. o_trapDoor@p_oCloseString := "The trapdoor cannot be closed.".
  1015. o_trapDoor@p_oNotLocked := true.
  1016. define tp_mall UTILITY_PIT_ID NextEffectId().
  1017. define tp_mall proc drawInsideDoor()void:
  1018.  
  1019.     if not KnowsEffect(nil, UTILITY_PIT_ID) then
  1020.     DefineEffect(nil, UTILITY_PIT_ID);
  1021.     GSetImage(nil, "utilityPit");
  1022.     IfFound(nil);
  1023.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  1024.     Else(nil);
  1025.         GSetPen(nil, C_DARK_BROWN);
  1026.         GAMove(nil, 0, 0);
  1027.         GRectangle(nil, 159, 99, true);
  1028.         GSetPen(nil, C_LIGHT_GREY);
  1029.         GAMove(nil, 65, 41);
  1030.         GRectangle(nil, 30, 18, true);
  1031.         GSetPen(nil, C_DARK_GREY);
  1032.         GAMove(nil, 95, 46);
  1033.         VerticalDoor();
  1034.         DrawUpArrow(C_GOLD);
  1035.     Fi(nil);
  1036.     EndEffect();
  1037.     fi;
  1038.     CallEffect(nil, UTILITY_PIT_ID);
  1039. corp;
  1040. AutoGraphics(r_underMall5, drawInsideDoor).
  1041. RoomName(r_underMall5, "Pit", "").
  1042.  
  1043. define tp_mall r_underMall6 CreateThing(r_indoors).
  1044. SetupRoom(r_underMall6, "in a north-south utility tunnel",
  1045.     "Large pipes and cable trays line both walls of the tunnel. It is quite "
  1046.     "warm and fairly noisy in here. The floor here is a metal grillwork over "
  1047.     "a small pit. There is a trapdoor in the grillwork and you can make out "
  1048.     "a staircase going down beneath it.").
  1049. Connect(r_underMall5, r_underMall6, D_UP).
  1050. Scenery(r_underMall6,
  1051.     "grill;metal.grillwork;metal."
  1052.     "pipe;large."
  1053.     "tray;cable,large."
  1054.     "floor;metal,grill,grillwork."
  1055.     "wall;both."
  1056.     "pit;small."
  1057.     "staircase").
  1058. AddTail(r_underMall6@p_rContents, o_trapDoor).
  1059. define tp_mall UTILITY_START_ID NextEffectId().
  1060. define tp_mall proc drawAbovePit()void:
  1061.     int i;
  1062.  
  1063.     if not KnowsEffect(nil, UTILITY_START_ID) then
  1064.     DefineEffect(nil, UTILITY_START_ID);
  1065.     GSetImage(nil, "utilityStart");
  1066.     IfFound(nil);
  1067.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  1068.     Else(nil);
  1069.         drawUtilityTunnel();
  1070.         GSetPen(nil, C_MEDIUM_GREY);
  1071.         GAMove(nil, 65, 41);
  1072.         GRectangle(nil, 30, 18, false);
  1073.         GAMove(nil, 68, 42);
  1074.         for i from 0 upto 8 do
  1075.         GRDraw(nil, 0, 16);
  1076.         GRMove(nil, 3, -16);
  1077.         od;
  1078.     Fi(nil);
  1079.     EndEffect();
  1080.     fi;
  1081.     CallEffect(nil, UTILITY_START_ID);
  1082. corp;
  1083. AutoGraphics(r_underMall6, drawAbovePit).
  1084. RoomName(r_underMall6, "Utility", "Tunnel").
  1085.  
  1086. define t_mall r_underMall7 CreateThing(r_indoors).
  1087. SetupRoomP(r_underMall7, "in a north-south utility tunnel",
  1088.     "You can go north, but the way south is blocked by a metal grill across "
  1089.     "the tunnel. The grill apparently divides the tunnel into separate "
  1090.     "sections.").
  1091. Connect(r_underMall6, r_underMall7, D_SOUTH).
  1092. Scenery(r_underMall7, "grill;metal.grillwork;metal").
  1093. define tp_mall UTILITY_SOUTH_ID NextEffectId().
  1094. define tp_mall proc drawSouthEnd()void:
  1095.  
  1096.     if not KnowsEffect(nil, UTILITY_SOUTH_ID) then
  1097.     DefineEffect(nil, UTILITY_SOUTH_ID);
  1098.     GSetImage(nil, "utilitySouth");
  1099.     IfFound(nil);
  1100.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  1101.     Else(nil);
  1102.         drawUtilityTunnel();
  1103.         GSetPen(nil, C_MEDIUM_GREY);
  1104.         GAMove(nil, 65, 59);
  1105.         GRDraw(nil, 30, 0);
  1106.     Fi(nil);
  1107.     EndEffect();
  1108.     fi;
  1109.     CallEffect(nil, UTILITY_SOUTH_ID);
  1110. corp;
  1111. AutoGraphics(r_underMall7, drawSouthEnd).
  1112. RoomName(r_underMall7, "Utility", "Tunnel").
  1113.  
  1114. define t_mall r_underMall8 CreateThing(r_indoors).
  1115. SetupRoomP(r_underMall8, "in a north-south utility tunnel",
  1116.     "This large concrete tunnel is used to carry utility services such as "
  1117.     "steam, hot and cold water, electricity, communications, etc.").
  1118. Connect(r_underMall6, r_underMall8, D_NORTH).
  1119. AutoGraphics(r_underMall8, drawUtilityTunnel).
  1120. RoomName(r_underMall8, "Utility", "Tunnel").
  1121.  
  1122. define t_mall r_underMall9 CreateThing(r_indoors).
  1123. SetupRoomP(r_underMall9, "in a north-south utility tunnel",
  1124.     "You can go south, but the way north is blocked by a metal grill across "
  1125.     "the tunnel. The grill apparently divides the tunnel into separate "
  1126.     "sections.").
  1127. Connect(r_underMall8, r_underMall9, D_NORTH).
  1128. Scenery(r_underMall9, "grill;metal.grillwork;metal").
  1129. define tp_mall giftRegistry CreateThing(nil).
  1130. define tp_mall giftGivenList CreateThingListProp().
  1131. giftRegistry@giftGivenList := CreateThingList().
  1132. define tp_mall proc checkForGift()status:
  1133.     thing me;
  1134.  
  1135.     me := Me();
  1136.     if FindElement(giftRegistry@giftGivenList, me) = -1 then
  1137.     AddTail(giftRegistry@giftGivenList, me);
  1138.     Print("You find 100 blutos!\n");
  1139.     me@p_pMoney := me@p_pMoney + 100;
  1140.     fi;
  1141.     continue
  1142. corp;
  1143. AddAnyEnterChecker(r_underMall9, checkForGift, false).
  1144. define tp_mall UTILITY_NORTH_ID NextEffectId().
  1145. define tp_mall proc drawNorthEnd()void:
  1146.  
  1147.     if not KnowsEffect(nil, UTILITY_NORTH_ID) then
  1148.     DefineEffect(nil, UTILITY_NORTH_ID);
  1149.     GSetImage(nil, "utilityNorth");
  1150.     IfFound(nil);
  1151.         GShowImage(nil, "", 0, 0, 160, 100, 0, 0);
  1152.     Else(nil);
  1153.         drawUtilityTunnel();
  1154.         GSetPen(nil, C_MEDIUM_GREY);
  1155.         GAMove(nil, 65, 41);
  1156.         GRDraw(nil, 30, 0);
  1157.     Fi(nil);
  1158.     EndEffect();
  1159.     fi;
  1160.     CallEffect(nil, UTILITY_NORTH_ID);
  1161. corp;
  1162. AutoGraphics(r_underMall9, drawNorthEnd).
  1163. RoomName(r_underMall9, "Utility", "Tunnel").
  1164.  
  1165. unuse tp_mall
  1166.